why use typescript generics